#include <iostream>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/wait.h>
#include <signal.h>
#include <unistd.h>
#include <arpa/inet.h>
#include "server_socket.h"
#include "common_gestor_envios.h"
#define PENDIENTES 10
#define SHUTDOWN 2

using std::cerr;
using std::endl;
using std::string;

Server_socket::Server_socket(int port) {
    fd = socket(AF_INET, SOCK_STREAM, 0);
    addr.sin_family = AF_INET; // Ordenación de bytes de la máquina
    addr.sin_port = htons(port); // Ordenación de bytes de la red
    addr.sin_addr.s_addr = INADDR_ANY; // Rellenar con mi dirección IP
    memset(&(addr.sin_zero), '\0', 8); // Poner a cero el resto
    if (fd == -1) {
        cerr << "server socket constructor" << endl;
    }
    int num = 1;
    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &num, sizeof (int)) == -1) {
        cerr << "server socket setsockopt" << endl;
    }
}

Server_socket::Server_socket() {
}

Server_socket::~Server_socket() {
}

int Server_socket::get_fd() {
    return fd;
}

struct sockaddr_in Server_socket::get_addr() {
    return addr;
}

int Server_socket::escuchar_puerto() {
    if (bind(fd, (const struct sockaddr*) &addr, sizeof (struct sockaddr)) == -1) {
        cerr << "server socket bind" << endl;
        return -1;
    }
    if (listen(fd, PENDIENTES) == -1) {
        cerr << "server socket listen" << endl;
        return -1;
    }
    return 0;
}

int Server_socket::aceptar_conexion(Server_socket* nuevo) {
    socklen_t size = sizeof (struct sockaddr_in);
    if ((nuevo->fd = accept(fd, (struct sockaddr*) &(nuevo->addr), &size))
            == -1) {
        cerr << "accept" << endl;
        return -1;
    }
    return 0;
}

int Server_socket::enviar(int aux_fd, string buffer, int tam) {
    return gestor->enviar(aux_fd, buffer, tam);
}

int Server_socket::recibir(int aux_fd, string* buffer, int tam) {
    return gestor->recibir(aux_fd, buffer, tam);
}

void Server_socket::cerrar_comunicacion() {
    if (shutdown(fd, SHUTDOWN) == -1) {
        cerr << "shutdown" << endl;
    }
}

void Server_socket::cerrar() {
    close(fd);
}
